/*
 * author: VDaras
 */

#include "Drawable.h"

#include "sdl/GLColor.h"
#include "Camera.h"
#include "RenderingManager.h"

Drawable::Drawable() : m_color(gl::colors::WHITE),m_blending(gl::BLEND_ALPHA), m_scale(1, 1)
{
    m_display = NULL;
    m_visible = true;
    memset( m_flip, 0, sizeof(bool )*2 );
    m_angle = 0;
    m_registeredTo = NULL;
}

Drawable::Drawable(const Drawable &toCopy) : m_color(toCopy.m_color),m_blending(toCopy.m_blending), m_clip(toCopy.m_clip), m_scale(toCopy.m_scale)
{
    m_display = toCopy.m_display;

    if( m_display != NULL )
        m_display->IncreaseReference( );

    m_visible = toCopy.m_visible;

    memcpy( m_flip, toCopy.m_flip, sizeof(bool )*2 );

    m_registeredTo = toCopy.m_registeredTo;

    m_angle = toCopy.m_angle;

    if( m_registeredTo != NULL )
    {
        RenderLayer *layer = m_registeredTo->LocateDrawable( &toCopy );

        if( layer != NULL )
        {
            layer->AddDrawable( this );
        }
    }
}

Drawable::~Drawable()
{
    if( m_display != NULL )
        m_display->DecreaseReference( );

    if( m_registeredTo != NULL )
        m_registeredTo->UnregisterDrawable( this );
}

void Drawable::SetScale(Math::Vector2F scale)
{
    this->m_scale = scale;
}

Math::Vector2F Drawable::GetScale() const
{
    return m_scale;
}

void Drawable::SetClip(Math::Rect clip)
{
    this->m_clip = clip;
}

Math::Rect Drawable::GetClip() const
{
    return m_clip;
}

void Drawable::SetColor(gl::Color color)
{
    this->m_color = color;
}

gl::Color Drawable::GetColor() const
{
    return m_color;
}

void Drawable::SetVisible(bool visible)
{
    this->m_visible = visible;
}

bool Drawable::IsVisible() const
{
    return m_visible;
}

int Drawable::GetWidth() const
{
    if( m_display != NULL )
    {
        return m_display->GetRawData( )->GetWidth( );
    }

    return 0;
}

int Drawable::GetHeight() const
{
    if( m_display != NULL )
    {
        return m_display->GetRawData( )->GetHeight( );
    }

    return 0;
}

void Drawable::SetDisplay(const Resource<gl::Texture>* display)
{
    if( this->m_display != NULL )
    {
        this->m_display->DecreaseReference( );
        this->m_display = NULL;
    }

    this->m_display = const_cast < Resource<gl::Texture> * > ( display );
    this->m_display->IncreaseReference();
}

void Drawable::Hide()
{
    m_visible = false;
}

void Drawable::Show()
{
    m_visible = true;
}

void Drawable::SetAngle(float angle)
{
    this->m_angle = angle;
}

float Drawable::GetAngle() const
{
    return m_angle;
}

Drawable &Drawable::operator =( const Drawable &toAssign )
{
    if( this == &toAssign )
    {
        return *this;
    }

    //if this has allready a resource
    if( m_display != NULL )
    {
        m_display->DecreaseReference( );
        m_display = NULL;
    }

    if( m_registeredTo != NULL )
    {
        m_registeredTo->UnregisterDrawable( this );
    }

    m_registeredTo = toAssign.m_registeredTo;
    if( m_registeredTo != NULL )
    {
        RenderLayer *layer = m_registeredTo->LocateDrawable( &toAssign );

        if( layer != NULL )
        {
            layer->AddDrawable( this );
        }
    }

    m_display = toAssign.m_display;
    m_display->IncreaseReference( );

    m_visible = toAssign.m_visible;
    m_angle = toAssign.m_angle;

    return *this;
}

/**
 * Sets the Rendering Manager that this Drawable is registered to.
 *
 * @param renderer: the rendering manager that this Drawable is registered to.
 */

void Drawable::SetRenderingManager(RenderingManager* renderer)
{
    if( m_registeredTo != NULL )
    {
        m_registeredTo->UnregisterDrawable( this );
    }

    m_registeredTo = renderer;
}

void Drawable::SetBlending(gl::BlendingMethodName  blending)
{
    this->m_blending = blending;
}

gl::BlendingMethodName  Drawable::GetBlending() const
{
    return m_blending;
}

